package ink.metoo.gude.util

import jakarta.servlet.http.HttpServletRequest
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes

/**
 * IP 获取工具类
 * 提供多种方式获取客户端真实 IP 地址
 */
object IpUtil {

    // 常见代理服务器 Header 名称
    private val IP_HEADERS = listOf(
        "X-Forwarded-For",
        "Proxy-Client-IP",
        "WL-Proxy-Client-IP",
        "HTTP_X_FORWARDED_FOR",
        "HTTP_X_FORWARDED",
        "HTTP_X_CLUSTER_CLIENT_IP",
        "HTTP_CLIENT_IP",
        "HTTP_FORWARDED_FOR",
        "HTTP_FORWARDED",
        "HTTP_VIA",
        "REMOTE_ADDR"
    )

    /**
     * 从 HttpServletRequest 获取客户端 IP 地址
     * @param request HttpServletRequest 对象
     * @return 客户端 IP 地址或 unknown
     */
    fun getClientIp(request: HttpServletRequest): String {
        // 遍历可能的代理 Header
        for (header in IP_HEADERS) {
            val ipList = request.getHeader(header) ?: continue
            if (ipList.isNotEmpty() && !"unknown".equals(ipList, true)) {
                // 多个 IP 的情况下取第一个非 unknown 的 IP
                val ips = ipList.split(",").map { it.trim() }
                for (ip in ips) {
                    if (!"unknown".equals(ip, true) && ip.isNotEmpty()) {
                        return ip
                    }
                }
            }
        }

        // 如果以上都没有获取到，使用 remoteAddr
        return request.remoteAddr ?: "unknown"
    }

    /**
     * 获取当前请求的客户端 IP 地址（通过 RequestContextHolder）
     * @return 客户端 IP 地址或 unknown
     */
    fun getCurrentClientIp(): String {
        val requestAttributes = RequestContextHolder.getRequestAttributes() as? ServletRequestAttributes
        return requestAttributes?.request?.let { getClientIp(it) } ?: "unknown"
    }

    /**
     * 验证 IP 地址是否为 IPv4 格式
     * @param ip 要验证的 IP 地址
     * @return 是否为有效的 IPv4 地址
     */
    fun isValidIPv4(ip: String): Boolean {
        val ipv4Pattern =
            Regex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")
        return ipv4Pattern.matches(ip)
    }

    /**
     * 获取 IP 地址的数值表示（用于比较或存储）
     * @param ip IPv4 地址字符串
     * @return IP 的数值表示，无效 IP 返回 null
     */
    fun ipToLong(ip: String): Long? {
        if (!isValidIPv4(ip)) return null

        val parts = ip.split(".").map { it.toLong() }
        return (parts[0] shl 24) + (parts[1] shl 16) + (parts[2] shl 8) + parts[3]
    }

    /**
     * 将数值表示的 IP 转换回字符串格式
     * @param ipLong IP 的数值表示
     * @return IPv4 地址字符串
     */
    fun longToIp(ipLong: Long): String {
        return ((ipLong shr 24) and 0xFF).toString() + "." +
                ((ipLong shr 16) and 0xFF).toString() + "." +
                ((ipLong shr 8) and 0xFF).toString() + "." +
                (ipLong and 0xFF).toString()
    }
}